Index: sys/netinet/tcp_syncache.c
===================================================================
RCS file: /home/ncvs/src/sys/netinet/tcp_syncache.c,v
retrieving revision 1.5.2.8
diff -c -r1.5.2.8 tcp_syncache.c
*** sys/netinet/tcp_syncache.c	18 Aug 2002 22:04:47 -0000	1.5.2.8
--- sys/netinet/tcp_syncache.c	23 Feb 2003 14:38:20 -0000
***************
*** 1222,1243 ****
  
  /*
   * The values below are chosen to minimize the size of the tcp_secret
!  * table, as well as providing roughly a 4 second lifetime for the cookie.
   */
  
! #define SYNCOOKIE_HASHSHIFT	2	/* log2(# of 32bit words from hash) */
! #define SYNCOOKIE_WNDBITS	7	/* exposed bits for window indexing */
! #define SYNCOOKIE_TIMESHIFT	5	/* scale ticks to window time units */
  
- #define SYNCOOKIE_HASHMASK	((1 << SYNCOOKIE_HASHSHIFT) - 1)
  #define SYNCOOKIE_WNDMASK	((1 << SYNCOOKIE_WNDBITS) - 1)
! #define SYNCOOKIE_NSECRETS	(1 << (SYNCOOKIE_WNDBITS - SYNCOOKIE_HASHSHIFT))
  #define SYNCOOKIE_TIMEOUT \
      (hz * (1 << SYNCOOKIE_WNDBITS) / (1 << SYNCOOKIE_TIMESHIFT))
  #define SYNCOOKIE_DATAMASK 	((3 << SYNCOOKIE_WNDBITS) | SYNCOOKIE_WNDMASK)
  
  static struct {
! 	u_int32_t	ts_secbits;
  	u_int		ts_expire;
  } tcp_secret[SYNCOOKIE_NSECRETS];
  
--- 1222,1241 ----
  
  /*
   * The values below are chosen to minimize the size of the tcp_secret
!  * table, as well as providing roughly a 16 second lifetime for the cookie.
   */
  
! #define SYNCOOKIE_WNDBITS	5	/* exposed bits for window indexing */
! #define SYNCOOKIE_TIMESHIFT	1	/* scale ticks to window time units */
  
  #define SYNCOOKIE_WNDMASK	((1 << SYNCOOKIE_WNDBITS) - 1)
! #define SYNCOOKIE_NSECRETS	(1 << SYNCOOKIE_WNDBITS)
  #define SYNCOOKIE_TIMEOUT \
      (hz * (1 << SYNCOOKIE_WNDBITS) / (1 << SYNCOOKIE_TIMESHIFT))
  #define SYNCOOKIE_DATAMASK 	((3 << SYNCOOKIE_WNDBITS) | SYNCOOKIE_WNDMASK)
  
  static struct {
! 	u_int32_t	ts_secbits[4];
  	u_int		ts_expire;
  } tcp_secret[SYNCOOKIE_NSECRETS];
  
***************
*** 1247,1252 ****
--- 1245,1260 ----
  
  #define MD5Add(v)	MD5Update(&syn_ctx, (u_char *)&v, sizeof(v))
  
+ struct md5_add {
+ 	u_int32_t laddr, faddr;
+ 	u_int32_t secbits[4];
+ 	u_int16_t lport, fport;
+ };
+ 
+ #ifdef CTASSERT
+ CTASSERT(sizeof(struct md5_add) == 28);
+ #endif
+ 
  /*
   * Consider the problem of a recreated (and retransmitted) cookie.  If the
   * original SYN was accepted, the connection is established.  The second 
***************
*** 1262,1296 ****
  {
  	u_int32_t md5_buffer[4];
  	u_int32_t data;
! 	int wnd, idx;
  
! 	wnd = ((ticks << SYNCOOKIE_TIMESHIFT) / hz) & SYNCOOKIE_WNDMASK;
! 	idx = wnd >> SYNCOOKIE_HASHSHIFT;
  	if (tcp_secret[idx].ts_expire < ticks) {
! 		tcp_secret[idx].ts_secbits = arc4random();
  		tcp_secret[idx].ts_expire = ticks + SYNCOOKIE_TIMEOUT;
  	}
  	for (data = sizeof(tcp_msstab) / sizeof(int) - 1; data > 0; data--)
  		if (tcp_msstab[data] <= sc->sc_peer_mss)
  			break;
! 	data = (data << SYNCOOKIE_WNDBITS) | wnd;
  	data ^= sc->sc_irs;				/* peer's iss */
  	MD5Init(&syn_ctx);
  #ifdef INET6
  	if (sc->sc_inc.inc_isipv6) {
  		MD5Add(sc->sc_inc.inc6_laddr);
  		MD5Add(sc->sc_inc.inc6_faddr);
  	} else
  #endif
  	{
! 		MD5Add(sc->sc_inc.inc_laddr);
! 		MD5Add(sc->sc_inc.inc_faddr);
  	}
! 	MD5Add(sc->sc_inc.inc_lport);
! 	MD5Add(sc->sc_inc.inc_fport);
! 	MD5Add(tcp_secret[idx].ts_secbits);
  	MD5Final((u_char *)&md5_buffer, &syn_ctx);
! 	data ^= (md5_buffer[wnd & SYNCOOKIE_HASHMASK] & ~SYNCOOKIE_WNDMASK);
  	return (data);
  }
  
--- 1270,1311 ----
  {
  	u_int32_t md5_buffer[4];
  	u_int32_t data;
! 	int idx, i;
! 	struct md5_add add;
  
! 	idx = ((ticks << SYNCOOKIE_TIMESHIFT) / hz) & SYNCOOKIE_WNDMASK;
  	if (tcp_secret[idx].ts_expire < ticks) {
! 		for (i = 0; i < 4; i++)
! 			tcp_secret[idx].ts_secbits[i] = arc4random();
  		tcp_secret[idx].ts_expire = ticks + SYNCOOKIE_TIMEOUT;
  	}
  	for (data = sizeof(tcp_msstab) / sizeof(int) - 1; data > 0; data--)
  		if (tcp_msstab[data] <= sc->sc_peer_mss)
  			break;
! 	data = (data << SYNCOOKIE_WNDBITS) | idx;
  	data ^= sc->sc_irs;				/* peer's iss */
  	MD5Init(&syn_ctx);
  #ifdef INET6
  	if (sc->sc_inc.inc_isipv6) {
  		MD5Add(sc->sc_inc.inc6_laddr);
  		MD5Add(sc->sc_inc.inc6_faddr);
+ 		add.laddr = 0;
+ 		add.faddr = 0;
  	} else
  #endif
  	{
! 		add.laddr = sc->sc_inc.inc_laddr.s_addr;
! 		add.faddr = sc->sc_inc.inc_faddr.s_addr;
  	}
! 	add.lport = sc->sc_inc.inc_lport;
! 	add.fport = sc->sc_inc.inc_fport;
! 	add.secbits[0] = tcp_secret[idx].ts_secbits[0];
! 	add.secbits[1] = tcp_secret[idx].ts_secbits[1];
! 	add.secbits[2] = tcp_secret[idx].ts_secbits[2];
! 	add.secbits[3] = tcp_secret[idx].ts_secbits[3];
! 	MD5Add(add);
  	MD5Final((u_char *)&md5_buffer, &syn_ctx);
! 	data ^= (md5_buffer[0] & ~SYNCOOKIE_WNDMASK);
  	return (data);
  }
  
***************
*** 1304,1313 ****
  	struct syncache *sc;
  	u_int32_t data;
  	int wnd, idx;
  
  	data = (th->th_ack - 1) ^ (th->th_seq - 1);	/* remove ISS */
! 	wnd = data & SYNCOOKIE_WNDMASK;
! 	idx = wnd >> SYNCOOKIE_HASHSHIFT;
  	if (tcp_secret[idx].ts_expire < ticks ||
  	    sototcpcb(so)->ts_recent + SYNCOOKIE_TIMEOUT < ticks)
  		return (NULL);
--- 1319,1328 ----
  	struct syncache *sc;
  	u_int32_t data;
  	int wnd, idx;
+ 	struct md5_add add;
  
  	data = (th->th_ack - 1) ^ (th->th_seq - 1);	/* remove ISS */
! 	idx = data & SYNCOOKIE_WNDMASK;
  	if (tcp_secret[idx].ts_expire < ticks ||
  	    sototcpcb(so)->ts_recent + SYNCOOKIE_TIMEOUT < ticks)
  		return (NULL);
***************
*** 1316,1332 ****
  	if (inc->inc_isipv6) {
  		MD5Add(inc->inc6_laddr);
  		MD5Add(inc->inc6_faddr);
  	} else
  #endif
  	{
! 		MD5Add(inc->inc_laddr);
! 		MD5Add(inc->inc_faddr);
  	}
! 	MD5Add(inc->inc_lport);
! 	MD5Add(inc->inc_fport);
! 	MD5Add(tcp_secret[idx].ts_secbits);
  	MD5Final((u_char *)&md5_buffer, &syn_ctx);
! 	data ^= md5_buffer[wnd & SYNCOOKIE_HASHMASK];
  	if ((data & ~SYNCOOKIE_DATAMASK) != 0)
  		return (NULL);
  	data = data >> SYNCOOKIE_WNDBITS;
--- 1331,1353 ----
  	if (inc->inc_isipv6) {
  		MD5Add(inc->inc6_laddr);
  		MD5Add(inc->inc6_faddr);
+ 		add.laddr = 0;
+ 		add.faddr = 0;
  	} else
  #endif
  	{
! 		add.laddr = inc->inc_laddr.s_addr;
! 		add.faddr = inc->inc_faddr.s_addr;
  	}
! 	add.lport = inc->inc_lport;
! 	add.fport = inc->inc_fport;
! 	add.secbits[0] = tcp_secret[idx].ts_secbits[0];
! 	add.secbits[1] = tcp_secret[idx].ts_secbits[1];
! 	add.secbits[2] = tcp_secret[idx].ts_secbits[2];
! 	add.secbits[3] = tcp_secret[idx].ts_secbits[3];
! 	MD5Add(add);
  	MD5Final((u_char *)&md5_buffer, &syn_ctx);
! 	data ^= md5_buffer[0];
  	if ((data & ~SYNCOOKIE_DATAMASK) != 0)
  		return (NULL);
  	data = data >> SYNCOOKIE_WNDBITS;
